package com.nondo.rdp.auth.service.impl;

import com.nondo.rdp.auth.endpoint.model.Page;
import com.nondo.rdp.auth.repository.DictRepository;
import com.nondo.rdp.auth.service.DictService;
import com.nondo.rdp.core.domain.Dict;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import java.util.ArrayList;
import java.util.List;

/**
 * com.seelyn.superp.core.service.impl
 *
 * @author linfeng
 * @since 2017/7/30
 */
@Service
@Transactional(readOnly = true)
public class DictServiceImpl implements DictService {

    @Autowired
    private DictRepository dictRepository;

    public Dict findOne(Long id) {
        return dictRepository.findById(id);
    }

    public Page<Dict> find(Page<Dict> page, Dict dict) {

        Sort sort = new Sort(Sort.Direction.ASC, "type");
        sort.and(new Sort(Sort.Direction.ASC, "sort"));
        PageRequest pageRequest = new PageRequest(page.getPageNumber(), page.getPageSize(), sort);
        org.springframework.data.domain.Page<Dict> dictPage = dictRepository.findAll((root, query, builder) -> {

            return initPredicate(dict, root, builder);

        }, pageRequest);

        return new Page<>(dictPage);

    }

    @Override
    @Cacheable(value = "dict", key = "'dict_' + #p0.type")
    public List<Dict> find(Dict dict) {
        Sort sort = new Sort(Sort.Direction.ASC, "type");
        sort.and(new Sort(Sort.Direction.ASC, "sort"));
        return dictRepository.findAll((root, query, builder) -> {

            return initPredicate(dict, root, builder);

        }, sort);

    }

    @Override
    public List<Dict> findListByType(String type) {

        Dict dict = new Dict();
        dict.setType(type);
        Sort sort = new Sort(Sort.Direction.ASC, "type");
        sort.and(new Sort(Sort.Direction.ASC, "sort"));
        return dictRepository.findAll((root, query, builder) -> {

            return initPredicate(dict, root, builder);

        }, sort);
    }

    private Predicate initPredicate(Dict dict, Root<Dict> root, CriteriaBuilder builder) {
        List<Predicate> predicates = new ArrayList<>();
        if (StringUtils.isNotEmpty(dict.getType())) {
            predicates.add(builder.equal(root.get("type").as(String.class), dict.getType()));
        }
        if (StringUtils.isNotEmpty(dict.getLabel())) {
            predicates.add(builder.equal(root.get("label").as(String.class), dict.getLabel()));
        }

        predicates.add(builder.equal(root.get("delFlag"), Dict.DEL_FLAG_NORMAL));
        Predicate[] predicatesArray = new Predicate[predicates.size()];
        predicates.toArray(predicatesArray);
        return builder.and(predicatesArray);
    }

    public List<String> findTypeList() {
        return dictRepository.findTypeList();
    }

    @Transactional(readOnly = false)
    public void save(Dict dict) {
        dictRepository.save(dict);
    }

    @Transactional(readOnly = false)
    public void delete(Long id) {
        dictRepository.deleteById(id);
    }

}
